/*
 * Copyright (C) 2021 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the
 *       distribution.
 *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include <stdlib.h>
#include <securec.h>
#include "driver/chip/private/hal_os.h"
#include "adc_core.h"
#include "driver/chip/hal_adc.h"
#include "hdf_platform.h"
#include "device_resource_if.h"

// HAL_Semaphore voltage_sem;
// #define ADC_VOL_SEM_INIT() HAL_SemaphoreInitBinary(&voltage_sem)
// #define ADC_VOL_SEM_WAIT() HAL_SemaphoreWait(&voltage_sem, HAL_WAIT_FOREVER)
// #define ADC_VOL_SEM_RELEASE() HAL_SemaphoreRelease(&voltage_sem)
// #define ADC_VOL_SEM_DEINIT() HAL_SemaphoreDeinit(&voltage_sem)

static int32_t AdcHostRead(struct AdcDevice *device, uint32_t channel,
			   uint32_t *val)
{
	HAL_Status status = HAL_ERROR;
    if (device == NULL) {
		return HDF_FAILURE;
	}
    status = HAL_ADC_Conv_Polling((ADC_Channel)channel, val, 10000);
	if (status != HAL_OK) {
		printf("HAL_ADC_Conv_Polling return: hal_status = %d\n", status);
		return HDF_ERR_DEVICE_BUSY;
	}
    return HDF_SUCCESS;
}

int32_t AdcHostStart(struct AdcDevice *device)
{
	return HDF_SUCCESS;
}
int32_t AdcHostStop(struct AdcDevice *device)
{
    return HDF_SUCCESS;
}
const struct AdcMethod g_adcHostMethod = {
	.read = AdcHostRead,
	.start = AdcHostStart,
	.stop = AdcHostStop,
};

static int32_t AdcDriverBind(struct HdfDeviceObject *device)
{
	if (device == NULL) {
		printf("%s: adc device object is NULL\r\n", __func__);
		return -1;
	}
	return HDF_SUCCESS;
}

static int32_t AttachAdcDevice(struct AdcDevice *adctrl,
			       struct HdfDeviceObject *device)
{
	ADC_InitParam initParam;

	if (device->property == NULL) {
		HDF_LOGD("%s: adc property is NULL\n", __func__);
		return HDF_FAILURE;
	}

	struct DeviceResourceIface *dri =
		DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
	if (dri == NULL || dri->GetUint32 == NULL) {
		HDF_LOGD("DeviceResourceIface is invalid\n");
		return HDF_FAILURE;
	}
	dri->GetUint32(device->property, "work_clk", &initParam.work_clk, 0);
	printf("work_clk = %d\n", initParam.work_clk);
	dri->GetUint32(device->property, "delay", &initParam.delay, 0);
	printf("delay = %d\n", initParam.delay);
	dri->GetUint32(device->property, "suspend_bypass",
		       &initParam.suspend_bypass, 0);
	printf("suspend_bypass = %d\n", initParam.suspend_bypass);
	dri->GetUint32(device->property, "vref_mode", &initParam.vref_mode, 0);
	printf("vref_mode = %d\n", initParam.vref_mode);
	dri->GetUint32(device->property, "mode", &initParam.mode, 0);
	printf("mode = %d\n", initParam.mode);
	// ADC_VOL_SEM_INIT();
	return (int32_t)HAL_ADC_Init(&initParam);
}

static int32_t AdcDriverInit(struct HdfDeviceObject *device)
{
	int ret;
	struct AdcDevice *AdcCntrl = NULL;

	if (device == NULL) {
		printf("%s: device is NULL\r\n", __func__);
		return HDF_ERR_INVALID_OBJECT;
	}

	if (AttachAdcDevice(AdcCntrl, device) != HAL_OK) {
		printf("%s: adc init fail!\r\n", __func__);
		return HDF_FAILURE;
	}

	AdcCntrl = malloc(sizeof(struct AdcDevice));
	if (AdcCntrl == NULL) {
		return HDF_ERR_MALLOC_FAIL;
	}
	memset(AdcCntrl, 0, sizeof(struct AdcDevice));

	AdcCntrl->ops = &g_adcHostMethod;
	/* 用于去初始化时释放内存 */
	device->priv = (void *)AdcCntrl;

	ret = AdcDeviceAdd(AdcCntrl);
	if (ret != HDF_SUCCESS) {
		printf("adcCntlrAdd failed!!ret = %d\n", ret);
		return HDF_FAILURE;
	}
	return ret;
}

static int32_t AdcDriverRelease(struct HdfDeviceObject *device)
{
	if (HAL_ADC_DeInit() != HAL_OK) {
		return HDF_FAILURE;
	}
	// ADC_VOL_SEM_DEINIT();
	free(device->priv);
	return HDF_SUCCESS;
}

/* HdfDriverEntry definitions */
struct HdfDriverEntry g_adcDriverEntry = {
	.moduleVersion = 1,
	.moduleName = "XRADIO_ADC",
	.Bind = AdcDriverBind,
	.Init = AdcDriverInit,
	.Release = AdcDriverRelease,
};

// Initialize HdfDriverEntry
HDF_INIT(g_adcDriverEntry);
